Skip to content

V1.17.7#689

Open
jasonacox wants to merge 10 commits intomasterfrom
v1.17.7
Open

V1.17.7#689
jasonacox wants to merge 10 commits intomasterfrom
v1.17.7

Conversation

@jasonacox
Copy link
Copy Markdown
Owner

v1.17.7 - UX Improvements

  • Scanner: Improved messaging for devices with no IP address — now clearly indicates the device may be battery-powered or sleeping and that local control is not supported, instead of the generic "Error: No IP found".
  • Wizard: When the Tuya Cloud API returns a "permission deny" error (or error code 1010), the wizard now prints a targeted hint suggesting the user check their IoT Core service subscription at https://iot.tuya.com.
  • README: Added troubleshooting notes clarifying battery-powered device limitations and warning against aggressive polling intervals that can cause devices to drop or reset their connection.
  • CLI (on, off, set, get): Improved handling of device local keys that contain special shell characters ($, #, =, :, !) - re: #688:
    • If --key is omitted and the key is not found in devices.json, the CLI now prompts interactively for the key. Input at a terminal prompt bypasses shell interpretation entirely, so no quoting or escaping is needed.
    • Added key length validation — Tuya local keys are always exactly 16 characters. If the resolved key is the wrong length (the most common symptom of a shell-escaping problem), a clear error is printed with platform-specific quoting tips for Linux/Mac and Windows CMD.

- Added troubleshooting notes in README for battery-powered device limitations and polling warnings.
- Enhanced scanner output to clarify when no IP is found, indicating potential battery-powered or offline status.
- Updated wizard to provide hints for "permission deny" errors, suggesting users check their Tuya IoT subscription.
- Bump version to 1.17.7.
Copilot AI review requested due to automatic review settings March 5, 2026 05:33
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

v1.17.7 focuses on UX improvements across the setup wizard, network scanner output, CLI ergonomics, and documentation to better guide users through common failure modes (battery/offline devices, cloud permission errors, and shell-escaping pitfalls for local keys).

Changes:

  • Wizard: add a targeted hint for “permission deny” / code 1010 Tuya Cloud errors.
  • Scanner/README/RELEASE: improve messaging + troubleshooting guidance around battery-powered/offline devices and polling frequency.
  • CLI: prompt for missing --key and validate local key length with clearer error tips.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
tinytuya/wizard.py Adds a “permission deny / 1010” hint when cloud calls fail.
tinytuya/scanner.py Updates “no IP” status line to be more descriptive.
tinytuya/core/core.py Bumps version tuple to 1.17.7.
tinytuya/__main__.py Improves CLI --key handling (prompt + length validation + usage tips).
RELEASE.md Adds release notes for v1.17.7.
README.md Adds troubleshooting notes on battery devices and polling rates.
Comments suppressed due to low confidence (3)

tinytuya/scanner.py:1845

  • This new message says "Battery-powered or offline", but the PR description/release notes say the scanner should also clearly indicate that local control is not supported when there is no IP. Consider updating the message here to include that local control isn't possible without an IP (and possibly that the device may be sleeping).
        print("    %s[%-25.25s] %sNo IP found - Battery-powered or offline%s" %
              (term.subbold, name, term.alertdim, term.normal))

tinytuya/wizard.py:196

  • The 1010 detection uses a broad substring match ('1010' in str(err)), which can produce false positives if other codes/messages contain that sequence. Since Cloud errors appear to be formatted like "Code 1010" (see Cloud.py), consider matching more specifically (e.g., checking for "code 1010" case-insensitively) or extracting the numeric code when available.
            if 'permission' in str(err).lower() or '1010' in str(err):
                print(bold + 'Hint: ' + dim + 'This may indicate your Tuya IoT subscription has expired.')

tinytuya/wizard.py:216

  • This same hint logic is duplicated in multiple error branches. Consider factoring it into a small helper (or a local function) so future changes to the hint text/conditions only need to be made once.
            if 'permission' in str(err).lower() or '1010' in str(err):
                print(bold + 'Hint: ' + dim + 'This may indicate your Tuya IoT subscription has expired.')
                print('      Visit https://iot.tuya.com to check and renew your IoT Core service.')

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

- Strip leading/trailing whitespace from keys from all sources (--key,
  devices.json, prompt) before length validation, preventing false
  failures from copy-paste artifacts
- Guard interactive key prompt with sys.stdin.isatty(); non-interactive
  contexts (cron, CI, piped input) now exit with a clear error instead
  of blocking indefinitely
- Switch key prompt from input() to getpass.getpass() so the key is not
  echoed to the terminal or captured in screen recordings/logs; prompt
  text notes that input is hidden
@uzlonewolf
Copy link
Copy Markdown
Collaborator

At some point I would like to add something like the "monitor" example to make it easier for people with devices that only send updates asynchronously to figure that out (i.e. #673). Call it monitor? I'll see if I can find time to add it later today.

@jasonacox
Copy link
Copy Markdown
Owner Author

I love that idea!

# using devices.json
tinytuya monitor --name "Kitchen Light"

# direct
tinytuya monitor --id $DEVICE_ID --key $KEY --ip $IP --version $VER

@uzlonewolf
Copy link
Copy Markdown
Collaborator

I felt __main__ was starting to grow a bit too big and so I moved all the CLI functions into a new file, cli.py.

I also reworked the argpase config a bit and moved the CLI commands up into the main for loop. This allows it to pick up both -debug options as well as the scanner -maxtime/-force/etc options.

I kinda want to add keyboard-interactive DP set commands now but that's going to have to wait for next time 😆

@uzlonewolf
Copy link
Copy Markdown
Collaborator

uzlonewolf commented Mar 8, 2026

Oh yeah, either --id or --name are now required and are mutually exclusive, I reworked a few of the messages, and omitting --version now kicks off a scan instead of defaulting to v3.3.

@uzlonewolf
Copy link
Copy Markdown
Collaborator

The fact that all the old commands use -arg but all the new ones use --arg is going to irk me to no end now 😆

@jasonacox
Copy link
Copy Markdown
Owner Author

The fact that all the old commands use -arg but all the new ones use --arg is going to irk me to no end now 😆

I thought the same. I'm glad you added the option for both formats... honors the old API but accomodates the more modern --.

@jasonacox
Copy link
Copy Markdown
Owner Author

I thought about merging this separate from documentation, but since the doc changes are simple, it is probably good to combine under same version. Let me know if you agree.

@uzlonewolf
Copy link
Copy Markdown
Collaborator

Sounds good to me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants